home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / util / boot / caboomsr.lha / CaBoom / SFPatch.h < prev    next >
C/C++ Source or Header  |  1995-08-24  |  3KB  |  151 lines

  1. #ifndef SFPATCH_H
  2. #define SFPATCH_H
  3. /*
  4.  * SFPatch.h 1.0
  5.  *
  6.  * Lee Kindness
  7.  *
  8.  * Public Domain
  9.  *
  10.  */
  11.  
  12. /* Includes */
  13.  
  14. #include <exec/types.h>
  15. #include <exec/memory.h>
  16. #include <proto/exec.h>
  17. #include <proto/dos.h>
  18. #include <proto/intuition.h>
  19.  
  20. /* Structures */
  21.  
  22. enum {
  23.     JMPINSTR = 0x4ef9
  24. };
  25.  
  26. typedef struct JmpEntry {
  27.     UWORD Instr;
  28.     APTR Func;
  29. } JmpEntry;
  30.  
  31. typedef struct SetFunc {
  32.     APTR            sf_Func;
  33.     APTR            sf_OriginalFunc;
  34.     JmpEntry       *sf_Jmp;
  35.     struct Library *sf_Library;
  36.     LONG            sf_Offset;
  37.     LONG            sf_QuitMethod;
  38.     LONG            sf_Count;
  39. } SetFunc;
  40.  
  41. /* Constants for SetFunc->sf_QuitMethod */
  42. #define SFQ_WAIT 0 /* wait sf_Count seconds (defaults to 3) */
  43. #define SFQ_COUNT 1 /* only quit if count == 0 (retry every 3 secs...) */
  44.  
  45. /* Prototypes */
  46.  
  47. BOOL SFReplace(SetFunc *sf);
  48. void SFRestore(SetFunc *sf);
  49.  
  50. /* The functions... */
  51.  
  52. /*
  53.  * The main method for replacing an Amiga OS function as safe as
  54.  * possible is to place the function with a jump table that is
  55.  * allocated.  While the function is replaced, the jump table simply
  56.  * jumps to my routine:
  57.  *
  58.  * jmp  _new_Function
  59.  *
  60.  * When the user asks the program to quit, we can't simply put the
  61.  * pointer back that SetFunction() gives us since someone else might
  62.  * have replaced the function.  So, we first see if the pointer we
  63.  * get back points to the out jump table.  If so, then we _can_ put
  64.  * the pointer back like normal (no one has replaced the function
  65.  * while we has it replaced).  But if the pointer isn't mine, then
  66.  * we have to replace the jump table function pointer to the old
  67.  * function pointer:
  68.  *
  69.  * jmp  _old_Function
  70.  *
  71.  * Finally, we only deallocate the jump table _if_ we did not have
  72.  * to change the jump table.
  73.  */
  74.  
  75.  
  76. BOOL SFReplace(SetFunc *sf)
  77. {
  78.     BOOL ret;
  79.     ret = FALSE;
  80.     /* Allocate the jump table */
  81.     if (sf->sf_Jmp = AllocVec(sizeof(JmpEntry), MEMF_CLEAR)) {
  82.         Forbid();
  83.  
  84.         /* Replace the function with pointer to jump table */
  85.         sf->sf_OriginalFunc = SetFunction(sf->sf_Library, sf->sf_Offset, (APTR)sf->sf_Jmp);
  86.  
  87.         /* Setup the jump table */
  88.         sf->sf_Jmp->Instr = JMPINSTR;
  89.         sf->sf_Jmp->Func = sf->sf_Func;
  90.  
  91.         // Clear the cpu's cache so the execution cache is valid
  92.         CacheClearU();
  93.  
  94.         Permit();
  95.         
  96.         /* muck around with the quit stuff... */
  97.         if (sf->sf_QuitMethod == SFQ_WAIT) {
  98.             if (sf->sf_Count <= 0)
  99.                 sf->sf_Count = 3;
  100.         } else
  101.             sf->sf_Count = 0;
  102.         ret = TRUE;
  103.     }
  104.     return ret;
  105. }
  106.  
  107. void SFRestore(SetFunc *sf)
  108. {
  109.     BOOL my_table;
  110.     ULONG (*func)();
  111.  
  112.     Forbid();
  113.  
  114.     /* Put old pointer back and get current pointer at same time */
  115.     func = SetFunction(sf->sf_Library, sf->sf_Offset, sf->sf_OriginalFunc);
  116.  
  117.     /* Check to see if the pointer we get back is ours */
  118.     if ((JmpEntry *)func != sf->sf_Jmp) {
  119.         /* If not, leave jump table in place */
  120.         my_table = FALSE;
  121.         SetFunction(sf->sf_Library, sf->sf_Offset, func);
  122.         sf->sf_Jmp->Func = sf->sf_OriginalFunc;
  123.     } else {
  124.         /* If so, free the jump table */
  125.         my_table = TRUE;
  126.         FreeVec(sf->sf_Jmp);
  127.     }
  128.  
  129.     /* Clear the cpu's cache so the execution cache is valid */
  130.     CacheClearU();
  131.  
  132.     Permit();
  133.  
  134.     /* Let the user know if the jump table couldn't be freed */
  135.     if ((!my_table) && (IntuitionBase))
  136.         DisplayBeep(NULL);
  137.     
  138.     /* Wait... */
  139.     if (sf->sf_QuitMethod == SFQ_WAIT) {
  140.         /* Wait n seconds */
  141.         Delay(sf->sf_Count * 50);
  142.     } else {
  143.         /* wait until sf->sf_Count == 0 */
  144.         while (sf->sf_Count)
  145.             Delay(150);
  146.     }
  147. }
  148.  
  149. #endif /* SFPATCH_H */
  150.  
  151.